/*
 * Description: process priority handler
 */
#include "process_priority_accelerator.h"
#include "Windows.h"
#include "log.h"
#include "performance/utils/perf_utils.h"
#include "performance/perf_constants.h"

namespace PERF {
bool ProcessPriorityAccelerator::OnBegin(std::shared_ptr<PerfInfo> perfInfo)
{
    LOG_INFO("[PERF - OnBegin] - start.");
    if (perfInfo == nullptr) {
        LOG_ERR("[PERF - OnBegin] - perfInfo is null!");
        return false;
    }
    if (PRELOAD_OFFICE_APPS.find(perfInfo->appName) != PRELOAD_OFFICE_APPS.end()) {
        perfInfo->skipSign |= SKIP_SIGN_ABOVE_NORMAL_PROCESS_PRIORITY;
        return true;
    }
    LOG_INFO("[PERF - OnBegin] - processId: {}", perfInfo->processId);
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, perfInfo->processId);
    if (hProcess == nullptr) {
        LOG_ERR("[PERF - OnBegin] - get process handle failed, GLE: {}", GetLastError());
        perfInfo->skipSign |= SKIP_SIGN_ABOVE_NORMAL_PROCESS_PRIORITY;
        LOG_INFO("[PERF - OnBegin] - failed.");
        return false;
    }
    DWORD crtPriority = GetPriorityClass(hProcess);
    if (crtPriority == ABOVE_NORMAL_PRIORITY_CLASS || crtPriority == HIGH_PRIORITY_CLASS ||
        crtPriority == REALTIME_PRIORITY_CLASS) {
        perfInfo->skipSign |= SKIP_SIGN_ABOVE_NORMAL_PROCESS_PRIORITY;
        CloseHandle(hProcess);
        LOG_INFO("[PERF - OnBegin] - skipped.");
        return true;
    }
    perfInfo->originPriority = crtPriority;
    if (!SetPriorityClass(hProcess, ABOVE_NORMAL_PRIORITY_CLASS)) {
        LOG_INFO("[PERF - OnBegin] - set priority succeed. processId: {}, priority: {}", perfInfo->processId,
                 ABOVE_NORMAL_PRIORITY_CLASS);
    }
    CloseHandle(hProcess);
    LOG_INFO("[PERF - OnBegin] - succeed.");
    return true;
}

bool ProcessPriorityAccelerator::OnEnd(std::shared_ptr<PerfInfo> perfInfo)
{
    LOG_INFO("[PERF - OnEnd] - start.");
    if (perfInfo == nullptr) {
        LOG_ERR("[PERF - OnEnd] - perfInfo is null!");
        return false;
    }
    if (perfInfo->scene == PERF::PERF_SCENE::APP_INSTALL) {
        LOG_INFO("[PERF - OnEnd] - meet install scene");
        return false;
    }
    if (perfInfo->skipSign & SKIP_SIGN_ABOVE_NORMAL_PROCESS_PRIORITY) {
        LOG_INFO("[PERF - OnEnd] - skipped.");
        return true;
    }
    HANDLE hProcess = OpenProcess(PROCESS_SET_INFORMATION, false, perfInfo->processId);
    if (hProcess == nullptr) {
        LOG_ERR("[PERF - OnEnd] - get process handle failed, GLE: {}", GetLastError());
        LOG_INFO("[PERF - OnEnd] - failed.");
        return false;
    }
    if (!SetPriorityClass(hProcess, perfInfo->originPriority)) {
        LOG_DEBUG("[PERF - OnEnd] - reset priority succeed. processId: {}, priority: {}", perfInfo->processId,
                  perfInfo->originPriority);
    }
    CloseHandle(hProcess);
    LOG_INFO("[PERF - OnEnd] - succeed.");
    return true;
}
}  // namespace PERF